﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Surface;
using Microsoft.Surface.Presentation;
using Microsoft.Surface.Presentation.Controls;
using System.Windows.Ink;

namespace GestureControl
{
    public class GestureControl : ContentControl
    {
        private double angle = 0;
        public static readonly DependencyProperty GestureProperty;
        public String Gesture
        {
            get { return (String)GetValue(GestureControl.GestureProperty); }
            set { SetValue(GestureControl.GestureProperty, value); }
        }

        #region GestureEvent
        public delegate void GestureRoutedEventHandler(object sender, GestureRoutedEventArgs e);
        public static readonly RoutedEvent gestureEvent = EventManager.RegisterRoutedEvent(
            "GestureEvent", RoutingStrategy.Bubble, typeof(GestureRoutedEventHandler), typeof(GestureControl));

        public event GestureRoutedEventHandler GestureEvent
        {
            add { AddHandler(gestureEvent, value); }
            remove { RemoveHandler(gestureEvent, value); }
        }
        protected virtual void RaiseGestureEvent(String gesture)
        {
            GestureRoutedEventArgs newEventArgs = new GestureRoutedEventArgs(GestureControl.gestureEvent, gesture);
            RaiseEvent(newEventArgs);
        }
        #endregion

        static GestureControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(GestureControl), new FrameworkPropertyMetadata(typeof(GestureControl)));

            GestureControl.GestureProperty = DependencyProperty.Register("Gesture", typeof(String), typeof(GestureControl),
                    new FrameworkPropertyMetadata("None", new PropertyChangedCallback(OnGestureChanged)));
        }
        private static void OnGestureChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            //Debug.WriteLine("changed", "Gesture");
        }

        protected override void OnInitialized(EventArgs e)
        {
            base.OnInitialized(e);
            this.InitializeControl();
        }
        protected void InitializeControl()
        {
           base.AddHandler(SurfaceControl.PreviewContactDownEvent, new RoutedEventHandler(AreaDown));
           base.AddHandler(SurfaceInkCanvas.StrokeCollectedEvent, new RoutedEventHandler(AreaStrokeCollected));
        }
        // get angle from the first contact of the stroke
        protected void AreaDown(object source, RoutedEventArgs e)
        {
            ContactEventArgs c = (ContactEventArgs)e;
            this.angle = c.Contact.GetOrientation(this) - 270;
        }

        protected void AreaStrokeCollected(object source, RoutedEventArgs e)
        {
            Debug.WriteLine("collected", "Stroke");
            System.Windows.Controls.InkCanvasStrokeCollectedEventArgs tmp = e as System.Windows.Controls.InkCanvasStrokeCollectedEventArgs;
            // Apply a rotation with the angle of the first contact
            Matrix rot = Matrix.Identity;
            rot.Rotate(-this.angle);
            Stroke s = tmp.Stroke;
            s.Transform(rot, true);
            // Get a list of point from a Bezier curve
            StylusPointCollection tmp2 = s.GetBezierStylusPoints();
            // Generate a list of SurfaceGesturePoint, just X and Y but can be improve
            List<SurfaceGesturePoint> pointList = new List<SurfaceGesturePoint>();
            foreach (StylusPoint p in tmp2)
                pointList.Add(new SurfaceGesturePoint { X = p.X, Y = p.Y });
            // create the gesture analyser and set the list
            SurfaceGesture gesture = new SurfaceGesture(pointList, 10);
            // try to get a pattern from the list, if one, raise a event
            this.Gesture = gesture.GetPattern();
            if (this.Gesture != "None")
            {
                this.RaiseGestureEvent(this.Gesture);
            }
            // clear the stroke
            SurfaceInkCanvas ink = e.OriginalSource as SurfaceInkCanvas;
            ink.Strokes.Clear();
        }
    }
}
